package io.renren.modules.netty;


import cn.hutool.core.util.XmlUtil;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.EventLoop;
import io.netty.channel.SimpleChannelInboundHandler;
import io.renren.modules.delay.DelayQueueManager;
import io.renren.modules.equipment.EquipmentEntity;
import io.renren.modules.equipment.EquipmentService;
import io.renren.modules.netty.model.ElecmeterMessageHeader;
import io.renren.modules.netty.model.ElecmeterMessageObj;
import io.renren.util.HexUtils;
import io.renren.util.SpringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Node;

import java.security.MessageDigest;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Slf4j
public class LogicClientHandler extends SimpleChannelInboundHandler<Object> {
	private String md5key = "IJKLMNOPQRSTUVWX";

	private int unRecPongTimes = 0 ;
	// 定义客户端没有收到服务端的pong消息的最大次数
	private static final int MAX_UN_REC_PONG_TIMES = 3;
	private NettyClient nettyClient;
	private EquipmentService equipmentService = SpringUtils.getBean(EquipmentService.class);
	private XmlService xmlService = SpringUtils.getBean(XmlService.class);
	private DelayQueueManager delayQueueManager = SpringUtils.getBean(DelayQueueManager.class);
	public LogicClientHandler(NettyClient nettyClient) {
		this.nettyClient = nettyClient;
	}
	// 连接成功后，向server发送消息
	@Override
	public void channelActive(ChannelHandlerContext ctx)  {
		try {
			log.info("channel is active");
			String authStr = xmlService.auth();
			ctx.writeAndFlush(Unpooled.copiedBuffer(HexUtils.hexStr2Bytes(authStr)));
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		}
	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
		log.info("检测到心跳服务器断开！！！");
		final EventLoop eventLoop = ctx.channel().eventLoop();
		NettyClient nettyClient = SpringUtils.getBean(NettyClient.class);
		nettyClient.bootstrap();
//		eventLoop.schedule(() -> nettyClient.bootstrap(), 10L, TimeUnit.SECONDS);
		super.channelInactive(ctx);
	}


	@Override
	protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
		ElecmeterMessageObj messageObj = (ElecmeterMessageObj) msg;
		ElecmeterMessageHeader header = messageObj.getMessageHeader();
		String content = messageObj.getContent();
		Document root = XmlUtil.parseXml(content);
		Node typeNode = XmlUtil.getNodeByXPath("//root/common/type", root);
		Node buildNode = XmlUtil.getNodeByXPath("//root/common/building_id", root);
		Node gatewayNode = XmlUtil.getNodeByXPath("//root/common/gateway_id", root);
		switch (typeNode.getTextContent()) {
			case "sequence":
				Node sequence = XmlUtil.getNodeByXPath("//root/id_validate/sequence", root);
				String value = sequence.getTextContent() + md5key;
				byte[] secretBytes = MessageDigest.getInstance("md5").digest(value.getBytes());
				String md5Xml = xmlService.md5(secretBytes);
				log.info("md5xml " + md5Xml);
				ctx.writeAndFlush(Unpooled.copiedBuffer(HexUtils.hexStr2Bytes(md5Xml)));
				break;
			case "result":
				Node resultNode = XmlUtil.getNodeByXPath("//root/id_validate/result", root);
				String result = resultNode.getTextContent();
				if (!"pass".equals(result)) {
					log.info("md5 error");
				}
				String buildingId = buildNode.getTextContent();
				EqmContextMap.getInstance().put(buildingId, ctx);
				String deviceXml = xmlService.device();
				log.info("deviceXml " + deviceXml);
				ctx.writeAndFlush(Unpooled.copiedBuffer(HexUtils.hexStr2Bytes(deviceXml)));
				break;
			case "archives":
				buildingId = buildNode.getTextContent();
				String archivessAckXml = xmlService.archivesAck(buildingId, HexUtils.bytesToHexString(header.getSerializ()));
				ctx.writeAndFlush(Unpooled.copiedBuffer(HexUtils.hexStr2Bytes(archivessAckXml)));
				break;
			case "time":
				delayQueueManager.remove("notify");
				break;
		}
	}
	@Override
	public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
		super.userEventTriggered(ctx, evt);
//		if (evt instanceof IdleStateEvent) {
//			IdleStateEvent event = (IdleStateEvent) evt;
//			String type = "";
//			if (event.state() == IdleState.READER_IDLE) {
//				type = "read idle";
//			} else if (event.state() == IdleState.WRITER_IDLE) {
//				type = "write idle";
//			} else if (event.state() == IdleState.ALL_IDLE) {
//				type = "all idle";
//			}
//			log.info("userEvent type=" + type);
//			if(unRecPongTimes < MAX_UN_REC_PONG_TIMES){
//				sendPingMsg(ctx,CLIENTID);
//				unRecPongTimes++;
//			}else{
//				ctx.channel().close();
//			}
//		} else {
//			super.userEventTriggered(ctx, evt);
//		}
	}
}
